package juc2.base;

/**
 * 死锁案例
 */
public class DeadlockDemo {
    // 创建两个共享资源（锁对象）
    // 资源A和资源B分别代表不同的锁
    private static final Object resourceA = new Object();
    private static final Object resourceB = new Object();

    public static void main(String[] args) {
        // 线程1：尝试先获取resourceA，再获取resourceB
        Thread thread1 = new Thread(() -> {
            // 1. 线程1获取resourceA锁
            synchronized (resourceA) {
                System.out.println("线程1：已获取资源A，准备获取资源B...");

                // 模拟线程1获取资源A后做一些操作（增加死锁概率）
                try {
                    // 注意：sleep不会释放已持有的resourceA锁
                    Thread.sleep(100);
//                    resourceA.wait(); //解决死锁
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 2. 线程1尝试获取resourceB锁
                // 此时如果resourceB已被线程2持有，线程1会进入阻塞状态等待
                synchronized (resourceB) {
                    System.out.println("线程1：成功获取资源B，执行操作...");
                }
            }
        }, "线程1");

        // 线程2：尝试先获取resourceB，再获取resourceA（与线程1顺序相反）
        Thread thread2 = new Thread(() -> {
            // 1. 线程2获取resourceB锁
            synchronized (resourceB) {
                System.out.println("线程2：已获取资源B，准备获取资源A...");

                // 模拟线程2获取资源B后做一些操作（增加死锁概率）
                try {
                    // 同样，sleep不会释放已持有的resourceB锁
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                // 2. 线程2尝试获取resourceA锁
                // 此时如果resourceA已被线程1持有，线程2会进入阻塞状态等待
                synchronized (resourceA) {
                    System.out.println("线程2：成功获取资源A，执行操作...");
//                    resourceA.notify();  //唤醒awit的resourceA线程
                }
            }
        }, "线程2");

        // 启动两个线程
        thread1.start();
        thread2.start();
    }
}

